#ifndef USER_LIB_H
#define USER_LIB_H

#include "main.h"
#include "cmsis_os.h"

#ifndef user_malloc
#ifdef _CMSIS_OS_H
#define user_malloc pvPortMalloc
#else
#define user_malloc malloc
#endif
#endif

typedef __packed struct
{
    fp32 input;             //输入数据
    fp32 out;               //输出数据
    fp32 min_value;         //限幅最小值
    fp32 max_value;         //限幅最大值
    fp32 frame_period;      //时间间隔
} ramp_function_source_t;

typedef __packed struct
{
    fp32 input;             //输入数据
    fp32 out;               //滤波输出的数据
    fp32 num[1];            //滤波参数
    fp32 frame_period;      //滤波的时间间隔 单位 s
} first_order_filter_type_t;

typedef __packed struct
{
    uint16_t Order;              // OLS 模型的阶数，表示数据点的数量
    uint32_t Count;              // 已处理的数据点数量，用于控制数据的更新
    fp32 *x;                     // 指向存储 x 值的数据数组（自变量）
    fp32 *y;                     // 指向存储 y 值的数据数组（因变量）
    fp32 k;                      // 线性回归的斜率（回归系数）
    fp32 b;                      // 线性回归的截距（偏置项）
    fp32 StandardDeviation;      // 标准差，表示回归模型拟合的精度
    fp32 t[4];                   // 临时存储中间计算值的数组，主要用于计算回归系数和标准差
} Ordinary_Least_Squares_t;

/**
  * @brief          快速开方
  * @author         RM
  * @param          num 输入数据
  * @retval         输出结果
  */
extern fp32 invSqrt(fp32 num);

/**
  * @brief          斜波函数初始化
  * @author         RM
  * @param          ramp_source_type 斜波函数结构体
  * @param          frame_period 间隔的时间，单位 s
  * @param          max 最大值
  * @param          min 最小值
  * @retval         返回空
  */
extern void ramp_init(ramp_function_source_t *ramp_source_type, fp32 frame_period, fp32 max, fp32 min);

/**
  * @brief          斜波函数计算，根据输入的值进行叠加， 输入单位为 /s 即一秒后增加输入的值
  * @author         RM
  * @param          ramp_source_type 斜波函数结构体
  * @param          input 滤波参数
  * @retval         返回空
  */
extern void ramp_calc(ramp_function_source_t *ramp_source_type, fp32 input);

/**
  * @brief          一阶低通滤波初始化
  * @author         RM
  * @param          first_order_filter_type 一阶低通滤波结构体
  * @param          frame_period 间隔的时间，单位 s
  * @param          num 滤波参数
  * @retval         返回空
  */
extern void first_order_filter_init(first_order_filter_type_t *first_order_filter_type, fp32 frame_period, const fp32 num[1]);

/**
  * @brief          一阶低通滤波计算
  * @author         RM
  * @param          first_order_filter_type 一阶低通滤波结构体
  * @param          input 间隔的时间，单位 s
  * @retval         返回空
  */
extern void first_order_filter_cali(first_order_filter_type_t *first_order_filter_type, fp32 input);

/**
  * @brief          绝对限制
  * @author         RM
  * @param          num 输入参数指针
  * @param          Limit 限制
  * @retval         返回空
  */
extern void abs_limit(fp32 *num, fp32 Limit);

/**
  * @brief          判断符号位
  * @author         RM
  * @param          value 输入
  * @retval         返回正负
  */
extern fp32 sign(fp32 value);

/**
  * @brief          浮点死区
  * @author         RM
  * @param          Value 输入值
  * @param          minValue 最小值
  * @param          maxValue 最大值
  * @retval         返回处理后的值。如果输入值在 `minValue` 和 `maxValue` 之间，返回 0.0f，否则返回原始值
  */
extern fp32 fp32_deadline(fp32 Value, fp32 minValue, fp32 maxValue);

/**
  * @brief          int16死区
  * @author         RM
  * @param          Value 输入值
  * @param          minValue 最小值
  * @param          maxValue 最大值
  * @retval         返回处理后的值。如果输入值在 `minValue` 和 `maxValue` 之间，返回 0，否则返回原始值
  */
extern int16_t int16_deadline(int16_t Value, int16_t minValue, int16_t maxValue);

/**
  * @brief          浮点限幅函数
  * @author         RM
  * @param          Value 输入值
  * @param          minValue 最小值
  * @param          maxValue 最大值
  * @retval         返回限制后的值。如果输入值小于 `minValue`，返回 `minValue`；如果大于 `maxValue`，返回 `maxValue`；否则返回原始值
  */
extern fp32 fp32_constrain(fp32 Value, fp32 minValue, fp32 maxValue);

/**
  * @brief          int16限幅函数
  * @author         RM
  * @param          Value 输入值
  * @param          minValue 最小值
  * @param          maxValue 最大值
  * @retval         返回限制后的值。如果输入值小于 `minValue`，返回 `minValue`；如果大于 `maxValue`，返回 `maxValue`；否则返回原始值
  */
extern int16_t int16_constrain(int16_t Value, int16_t minValue, int16_t maxValue);

/**
  * @brief          循环限幅函数，将输入值限制在指定的最小值和最大值之间，如果超出范围则循环回绕
  * @author         RM
  * @param          Input 输入值
  * @param          minValue 最小值
  * @param          maxValue 最大值
  * @retval         返回循环后的值。如果 `Input` 超出范围，则将其限制在 `[minValue, maxValue]` 范围内，超出的部分会从最小值或最大值回绕
  */
extern fp32 loop_fp32_constrain(fp32 Input, fp32 minValue, fp32 maxValue);

/**
  * @brief          将角度值限制在 -180 到 180 度之间
  * @author         RM
  * @param          Ang 输入角度值
  * @retval         返回格式化后的角度值，确保其在 [-180.0f, 180.0f] 范围内
  */
extern fp32 theta_format(fp32 Ang);

/**
  * @brief          对浮点数进行四舍五入操作
  * @author         冉文治
  * @param          raw 输入的浮点数
  * @retval         返回四舍五入后的整数值
  */
extern int32_t float_rounding(fp32 raw);

/**
  * @brief          初始化普通最小二乘（OLS）算法的相关参数
  * @author         冉文治
  * @param          OLS 指向 `Ordinary_Least_Squares_t` 结构体的指针，用于存储 OLS 的参数和数据
  * @param          order 数据的阶数，决定了 `x` 和 `y` 数组的大小
  * @retval         无返回值，初始化完成后，`OLS` 结构体包含了相应的参数和内存分配
  */
extern void OLS_Init(Ordinary_Least_Squares_t *OLS, uint16_t order);

/**
  * @brief          更新普通最小二乘（OLS）算法的参数，计算回归直线的斜率和截距
  * @author         冉文治
  * @param          OLS 指向 `Ordinary_Least_Squares_t` 结构体的指针，包含当前的 OLS 参数和数据
  * @param          deltax 当前位置的增量（x值的变化量）
  * @param          y 当前的 y 值（对应于 `deltax`）
  * @retval         无返回值，更新 OLS 结构体中的 `k`（斜率）、`b`（截距）以及标准差 `StandardDeviation`
  */
extern void OLS_Update(Ordinary_Least_Squares_t *OLS, fp32 deltax, fp32 y);

/**
  * @brief          更新普通最小二乘（OLS）算法的斜率（导数），并返回当前斜率值
  * @author         冉文治
  * @param          OLS 指向 `Ordinary_Least_Squares_t` 结构体的指针，包含当前的 OLS 参数和数据
  * @param          deltax 当前位置的增量（x值的变化量）
  * @param          y 当前的 y 值（对应于 `deltax`）
  * @retval         返回当前的斜率（`k`），即线性回归模型的导数
  */
extern fp32 OLS_Derivative(Ordinary_Least_Squares_t *OLS, fp32 deltax, fp32 y);

/**
  * @brief          获取当前普通最小二乘（OLS）算法的斜率（导数）
  * @author         冉文治
  * @param          OLS 指向 `Ordinary_Least_Squares_t` 结构体的指针，包含当前的 OLS 参数和数据
  * @retval         返回当前的斜率（`k`），即线性回归模型的导数
  */
extern fp32 Get_OLS_Derivative(Ordinary_Least_Squares_t *OLS);

/**
  * @brief          更新普通最小二乘（OLS）算法的参数，计算回归值并平滑输出
  * @author         冉文治
  * @param          OLS 指向 `Ordinary_Least_Squares_t` 结构体的指针，包含当前的 OLS 参数和数据
  * @param          deltax 当前位置的增量（x值的变化量）
  * @param          y 当前的 y 值（对应于 `deltax`）
  * @retval         返回平滑后的回归值
  */
extern fp32 OLS_Smooth(Ordinary_Least_Squares_t *OLS, fp32 deltax, fp32 y);

/**
  * @brief          获取当前普通最小二乘（OLS）算法的平滑输出值
  * @author         冉文治
  * @param          OLS 指向 `Ordinary_Least_Squares_t` 结构体的指针，包含当前的 OLS 参数和数据
  * @retval         返回当前平滑后的回归值
  */
extern fp32 Get_OLS_Smooth(Ordinary_Least_Squares_t *OLS);

// 弧度格式化为-PI~PI
#define rad_format(Ang) loop_fp32_constrain((Ang), -PI, PI)

#endif
